package com.wjerp.tplus.server.application.biz;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.wjerp.tplus.server.api.request.UpdateCompanyInfoRequest;
import com.wjerp.tplus.server.common.constant.ErrorDetail;
import com.wjerp.tplus.server.common.constant.LoginType;
import com.wjerp.tplus.server.common.constant.RedisKey;
import com.wjerp.tplus.server.common.constant.UserType;
import com.wjerp.tplus.server.common.exception.BusinessException;
import com.wjerp.tplus.server.common.exception.ServiceException;
import com.wjerp.tplus.server.common.model.BaseResponseData;
import com.wjerp.tplus.server.common.model.LoginResponse;
import com.wjerp.tplus.server.common.model.LoginUserDetailInfo;
import com.wjerp.tplus.server.common.model.LoginWrapper;
import com.wjerp.tplus.server.common.security.JwtTokenUtil;
import com.wjerp.tplus.server.common.utils.RedisUtils;
import com.wjerp.tplus.server.domain.entity.CompanyInfo;
import com.wjerp.tplus.server.domain.entity.CompanyUserRelation;
import com.wjerp.tplus.server.domain.entity.sys.UserInfo;
import com.wjerp.tplus.server.domain.mapper.CompanyUserRelationMapper;
import com.wjerp.tplus.server.domain.service.CompanyService;
import com.wjerp.tplus.server.domain.service.UserInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author lishuailei
 */
@Component
public class AuthenticationBiz{

    private Logger logger = LoggerFactory.getLogger(AuthenticationBiz.class);

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private JwtTokenUtil jwtTokenUtil;


    @Resource
    private UserInfoService userInfoService;

    @Resource
    private CompanyService companyService;

    @Resource
    private CompanyUserRelationMapper companyUserRelationMapper;

    @Resource
    private RedisUtils redisUtils;

    @Value("${wj.openApi.registerUrl}")
    private String registerUrl;

    @Value("${wj.openApi.systemUserId}")
    private String systemUserId;

    /**
     * 登录系统
     * @param request
     * @param loginWrapper
     * @return
     * @throws BusinessException
     */
    public LoginResponse loginPlatform(HttpServletRequest request, LoginWrapper loginWrapper) throws BusinessException {
        LoginResponse response = new LoginResponse();
        UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(
                loginWrapper.getUsername(),
                loginWrapper.getPassword());
        try {
            final Authentication authentication = authenticationManager.authenticate(upToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }catch (AuthenticationException ex){
            if(ex instanceof DisabledException){
                throw new BusinessException(ErrorDetail.DISABLE_USER);
            }
            throw new BusinessException(ErrorDetail.AUTH_INVALID_PASSWORD_USERNAME);
        }
        UserInfo userInfo = userInfoService.findByMobileOrEmail(loginWrapper.getUsername());

        if(!userInfo.getEnabled()){
            throw new BusinessException(ErrorDetail.DISABLE_USER);
        }

        LoginType  loginType = null;
        if(userInfo != null && userInfo.getUserType() != null){
            switch (loginWrapper.getLoginType()){
                case "1":
                    loginType = LoginType.PSP;
                    //后台(系统用户和机构)
                    if(!userInfo.getUserType().equals(UserType.ADMIN_USER.getCode())
                            && !userInfo.getUserType().equals(UserType.COMPANY_USER.getCode())){
                        throw new BusinessException(ErrorDetail.AUTH_UNKNOWN_LOGIN_TYPE);
                    }
                    break;
                case "2":
                    loginType = LoginType.MERCHANT;
                    //商户端
                    if(!userInfo.getUserType().equals(UserType.MERCHANT_USER.getCode())){
                        throw new BusinessException(ErrorDetail.AUTH_UNKNOWN_LOGIN_TYPE);
                    }
                    break;
                default:
                    throw new BusinessException(ErrorDetail.AUTH_UNKNOWN_LOGIN_TYPE);
            }
        }else {
            throw new BusinessException(ErrorDetail.AUTH_UNKNOWN_LOGIN_TYPE);
        }

        List<String>  roles= userInfoService.findUserPermissionByDisplayUserIdAndUserType(userInfo.getDisplayUserId(),userInfo.getUserType());
        CompanyInfo companyInfo = companyService.loadCompanyInfoByUserCode(userInfo.getDisplayUserId());
        String token = jwtTokenUtil.generateToken(userInfo,roles,companyInfo);
        response.setLoginType(loginType);
        response.setToken(token);
        response.setId(userInfo.getDisplayUserId());
        response.setUserType(userInfo.getUserType());
        return response;
    }

    /**
     * 系统注册
     * @param authCode 授权编码
     */
    public void sysRegister(String authCode) throws ServiceException, BusinessException {
        //判断当前系统是否已经注册
        CompanyInfo companyInfo = companyService.loadCompanyInfoByAuthCode(authCode);
        if(companyInfo !=null){
            throw new ServiceException("系统已经注册无需重复注册");
        }

        //1.调用openApi进行系统注册
        String result = HttpUtil.get(registerUrl+authCode);
        BaseResponseData baseResponseData = JSON.parseObject(result, BaseResponseData.class);
        if(baseResponseData.isSuccess()){
            //获取当前系统的用户信息
            UserInfo userInfo = userInfoService.findUserInfoByDisplayUserId(systemUserId);
            //获取返回的公司信息对象
            companyInfo = JSON.parseObject(JSON.toJSONString(baseResponseData.getData()), CompanyInfo.class);
            //新增公司信息
            companyInfo.setCreatedUser(userInfo.getDisplayUserId());
            companyInfo.setUpdatedUser(userInfo.getDisplayUserId());
            companyInfo.setId(null);
            UpdateCompanyInfoRequest request = new UpdateCompanyInfoRequest();
            BeanUtils.copyProperties(companyInfo,request);
            companyService.addOrUpdateCompanyInfo(systemUserId,request);

            //建立公司与用户之间的关系
            CompanyUserRelation companyUserRelation = new CompanyUserRelation();
            companyUserRelation.setUserCode(userInfo.getDisplayUserId());
            companyUserRelation.setCompanyCode(companyInfo.getCompanyCode());
            companyUserRelationMapper.insertSelective(companyUserRelation);

            redisUtils.set(RedisKey.AUTH_CODE,authCode);
        }else{
            throw new ServiceException(baseResponseData.getErrorCode(),baseResponseData.getErrorMsg());
        }
    }
}